#!/usr/bin/env php
<?php
/**
 * Yii Application Initialization Tool
 *
 * In order to run in non-interactive mode:
 *
 * init --env=Development --overwrite=n
 *
 * @author Alexander Makarov <sam@rmcreative.ru>
 *
 * @link http://www.yiiframework.com/
 * @copyright Copyright (c) 2008 Yii Software LLC
 * @license http://www.yiiframework.com/license/
 */
if (!extension_loaded('openssl')) {
    die('The OpenSSL PHP extension is required by Yii2.');
}
$envs = ['dev', 'test', 'prod'];

$params = getParams();
if(empty($params['env'])) {//强制要求配置环境
    echo "Which environment do you want the application to be initialized in?\n\n";
    foreach($envs as $i => $name) {
        echo " [$i] $name".PHP_EOL;
    }
    echo "\n  Your choice [0-" . (count($envs) - 1) . ', or "q" to quit] ';
    $answer = trim(fgets(STDIN));
    if (!ctype_digit($answer) || !in_array($answer, range(0, count($envs) - 1))) {
        echo "\n  Quit initialization.\n";
        exit(0);
    }
    $env = $envs[$answer];
} else {
    $env = $params['env'];
}
if(!in_array($env, $envs)) {
    echo "\n $env is not a valid environment, try one of the following: ".implode(',', $envs);
    exit(2);
}

echo "\n  Initialize the application under '{$env}' environment? [yes|no] ";
$answer = trim(fgets(STDIN));
if ($answer !== 'yes') {
    echo "\n  Quit initialization.\n";
    exit(0);
}

echo "\n  Start initialization ...\n\n";

$root = str_replace('\\', '/', __DIR__);

if(!empty($params['create'])) {
    $project = $params['create'];
    if(file_exists($root.'/'.$project)) {
        echo "\n {$project} has been exist under root path \n Quit";
        exit;
    }
    $files = getFileList("$root/environments/demo");
    //复制基本文件
    foreach ($files as $file) {
        if (!copyProject($project.'/'.$file, "environments/demo/{$file}")) {
            break;
        }
    }
} else {
    if(empty($params[0])) {
        echo "\n you have to type your project\n";
        exit();
    }
    $project = $params[0];//第一个
    if(!file_exists($root.'/'.$project)) {
        echo "\n {$project} not existed under root path \n Quit";
        exit;
    }
}
//复制main-test.php, params-test.php
copyEnvFile($root, $project, $env);

function copyEnvFile($root, $project, $env) {
    global $params;
    $files = [
        $root.'/'.$project.'/config/main-'.$env.'.php',
        $root.'/'.$project.'/config/params-'.$env.'.php',
        $root.'/common/config/main-'.$env.'.php',
        $root.'/common/config/params-'.$env.'.php',
    ];
    //overwrite 会影响到公共配置common/main-test.php，是否不太妥?
    foreach($files as $k=>$file) {
        if(!file_exists($file)) {
            $pathinfo = pathinfo($file);
            $devName = str_replace('-'.$env, '-dev', $pathinfo['basename']);
            $devFile = $pathinfo['dirname'].'/'.$devName;
            if(!file_exists($devFile)) {
                $string = "<?php return [];\n";
                file_put_contents($file, $string);
            } else {
                file_put_contents($file, file_get_contents($devFile));
            }
        }
    }
}

if(!empty($params['create'])) {
    setCookieValidationKey($root.'/'.$project.'/config/main-'.$env.'.php');
    setProjectNamespace($root, $project);
    setBootstrap($root, $project);
}

function setProjectNamespace($root, $project) {//配置命名空间
    $files = [
        $root.'/'.$project.'/config/main.php',
        $root.'/'.$project.'/assets/AppAsset.php',
        $root.'/'.$project.'/controllers/SiteController.php',
    ];
    foreach($files as $file) {
        $str = str_replace('{project}', $project, file_get_contents($file));
        file_put_contents($file, $str);
    }
}

function setBootstrap($root, $project) {
    $file = $root.'/common/config/bootstrap.php';
    $str = file_get_contents($file);
    if(!preg_match('/.*\@'.$project.'.*?/', $str)) {
        $new = 'Yii::setAlias(\'@'.$project.'\', dirname(dirname(__DIR__)) . \'/'.$project.'\');'.PHP_EOL;
        file_put_contents($file, $new, FILE_APPEND);
    }
}

function getFileList($root, $basePath = '')
{
    $files = [];
    $handle = opendir($root);
    while (($path = readdir($handle)) !== false) {
        if ($path === '.git' || $path === '.svn' || $path === '.' || $path === '..') {
            continue;
        }
        $fullPath = "$root/$path";
        $relativePath = $basePath === '' ? $path : "$basePath/$path";
        if (is_dir($fullPath)) {
            $files = array_merge($files, getFileList($fullPath, $relativePath));
        } else {
            $files[] = $relativePath;
        }
    }
    closedir($handle);
    return $files;
}

function copyProject($target, $source) {
    global $root;
    if (is_file($root . '/' . $target)) {
        file_put_contents($root . '/' . $target, file_get_contents($root . '/' . $source));
        return true;
    }
    echo "   generate $target\n";
    @mkdir(dirname($root . '/' . $target), 0777, true);
    file_put_contents($root . '/' . $target, file_get_contents($root . '/' . $source));
    return true;
}

function getParams()
{
    $rawParams = [];
    if (isset($_SERVER['argv'])) {
        $rawParams = $_SERVER['argv'];
        array_shift($rawParams);
    }

    $params = [];
    foreach ($rawParams as $param) {
        if (preg_match('/^--(\w+)(=(.*))?$/', $param, $matches)) {
            $name = $matches[1];
            $params[$name] = isset($matches[3]) ? $matches[3] : true;
        } else {
            $params[] = $param;
        }
    }
    return $params;
}

function setCookieValidationKey($file)
{
    echo "   generate cookie validation key in $file\n";
    if(!file_exists($file)) {
        return false;
    }
    $length = 32;
    $bytes = openssl_random_pseudo_bytes($length);
    $key = strtr(substr(base64_encode($bytes), 0, $length), '+/=', '_-.');
    $content = preg_replace('/(("|\')cookieValidationKey("|\')\s*=>\s*)(""|\'.*\')/', "\\1'$key'", file_get_contents($file));
    file_put_contents($file, $content);
}
